#include "handler.h"

using namespace std;
using namespace cv;

void Handler::ApplyWaterFilling(string source, string result, int first, int last)
{
	string ext = ".bmp";
	int amount = last - first;

	WaterFilling wf(100);
	for (int i = first; i < last; ++i)
	{
		Mat im_source = imread(source + to_string(i) + ext, CV_LOAD_IMAGE_GRAYSCALE);

		Mat im_result = wf.ApplyWaterFilling(im_source);
		cv::imwrite(result + to_string(i) + "e" + ext, im_result);
		cv::imwrite("data/d1d2/dep-" + to_string(i + 1500) + "e" + ext, im_result);

	}
	cout << "All: " << wf.allTime / amount << endl;
	cout << "Min: " << wf.minTime << endl;
	cout << "Max: " << wf.maxTime << endl;

	getchar();
}

void Handler::ApplyBackgroundSubtraction()
{
	string bgName = "data/micc_crowd/depth/";
	string filePath = "data/micc_crowd/depth/";
	string name = "63.png";
	string fileName = filePath + name;
	string res = "data/micc_crowd/res/" + name;

	//Mat bg = imread(bgName, CV_LOAD_IMAGE_GRAYSCALE);
	Mat bg = GetMedianBackground(bgName);
	Mat frame = imread(fileName, CV_LOAD_IMAGE_GRAYSCALE);

	Mat fg(cv::Size(bg.rows, bg.cols), CV_8U);

	for (int i = 0; i < bg.rows; ++i)
	{
		for (int j = 0; j < bg.cols; ++j)
		{
			if (bg.at<uchar>(i, j) != frame.at<uchar>(i, j))
			{
				//fg.at<uchar>(i, j) = frame.at<uchar>(i, j);
			}
			else
			{
				frame.at<uchar>(i, j) = 0;
			}
		}
	}
	imwrite(res, frame);


	// 	cv::BackgroundSubtractorMOG mog/* = BackgroundSubtractorMOG(10, 4, 4.5, 2.0)*/;
	// 	cv::BackgroundSubtractorMOG2 mog2/* = BackgroundSubtractorMOG2(40, 16, false)*/;
	// 
	// 	Mat frame;
	// 	Mat fgMaskMog;
	// 	Mat fgMaskMog2;
	// 	Mat background;
	// 
	// 	namedWindow("Frame");
	// 	namedWindow("FG Mask MOG");
	// 	namedWindow("FG Mask MOG 2");
	// 	namedWindow("Background");
	// 
	// 	string prefix = "data/micc_crowd/depth/";
	// 	//prefix = "../datasets/ucsdpeds/vidf/vidf1_33_009.y/vidf1_33_009_f0";
	// //	prefix = "../datasets/WaterFilling dataset/dataset1/Dep/dep-";
	// 	string postfix = ".png";
	// 	int number = 0;
	// 	int keyboard;
	// 
	// 	while (true)
	// 	{
	// 		cout << number << endl;
	// 		frame = imread(string(prefix + to_string(number) + postfix));
	// 		number++;
	// 
	// 		mog(frame, fgMaskMog);
	// 		mog2(frame, fgMaskMog2);
	// 
	// 		mog2.getBackgroundImage(background);
	// 
	// 		imshow("Frame", frame);
	// 		imshow("FG Mask MOG", fgMaskMog);
	// 		imshow("FG Mask MOG 2", fgMaskMog2);
	// 		imshow("Background", background);
	// 
	// 		keyboard = waitKey(0);
	// 		if ((char)keyboard == 'q')
	// 			break;
	// 	}
	// 
	// 	return 0;
}

cv::Mat Handler::GetMedianBackground(string path)
{
	int i = 0;
	int all = 38;
	Mat bg = imread(path + to_string(i) + ".png", CV_LOAD_IMAGE_GRAYSCALE);
	vector<float> median(bg.rows * bg.cols);

	for (; i <= all; ++i)
	{
		Mat next = imread(path + to_string(i) + ".png", CV_LOAD_IMAGE_GRAYSCALE);
		imshow("smth", next);
		waitKey(0);
		for (int r = 0; r < next.rows; ++r)
		{
			for (int c = 0; c < next.cols; ++c)
			{
				median[r * next.cols + c] += next.at<uchar>(r, c);
			}
		}
	}
	std::transform(median.begin(), median.end(), median.begin(), [&](float x){
		return x = float(x) / all;
	});

	for (int r = 0; r < bg.rows; ++r)
	{
		for (int c = 0; c < bg.cols; ++c)
		{
			bg.at<uchar>(r, c) = median[r * bg.cols + c];
		}
	}
	imwrite("data/micc_crowd/res/bg.png", bg);
	return bg;
}

void Handler::GetResults(std::string groundThruth, std::string result, int first, int last)
{
	Tester test;
	test.Compute(groundThruth, result, first, last);
	cout << "Accuracy: " << test.GetAccuracy() << endl;
	cout << "Recall: " << test.GetRecall() << endl;
	cout << "F-score: " << test.GetFScore() << endl;
	getchar();
}